/* * Author: Chris Seguin * * This software has been developed under the copyleft * rules of the GNU General Public License. Please * consult the GNU General Public License for more * details about use and distribution of this software. */ package org.acm.seguin.refactor.field; import org.acm.seguin.parser.ast.ASTFieldDeclaration; import org.acm.seguin.parser.ast.ASTName; import org.acm.seguin.parser.ast.SimpleNode; import org.acm.seguin.pretty.ModifierHolder; import org.acm.seguin.refactor.AddImportTransform; import org.acm.seguin.refactor.ComplexTransform; import org.acm.seguin.refactor.RefactoringException; import org.acm.seguin.summary.FileSummary; import org.acm.seguin.summary.TypeDeclSummary; import org.acm.seguin.summary.TypeSummary; import org.acm.seguin.summary.query.FieldQuery; import org.acm.seguin.summary.query.GetTypeSummary; /** * Performs the pullup field refactoring * *@author Chris Seguin */ public class PushUpFieldRefactoring extends FieldRefactoring { private TypeSummary parentType; /** * Constructor for the PushUpFieldRefactoring object */ protected PushUpFieldRefactoring() { } /** * Gets the description of the refactoring * *@return the description */ public String getDescription() { return "Moves a field " + field + " into parent class named " + parentType.getName(); } /** * Gets the ID attribute of the PushUpFieldRefactoring object * *@return The ID value */ public int getID() { return PUSH_UP_FIELD; } /** * Preconditions that must be true for the refactoring to work * *@exception RefactoringException a problem with performing this * refactoring */ protected void preconditions() throws RefactoringException { if (field == null) { throw new RefactoringException("No field specified"); } if (typeSummary == null) { throw new RefactoringException("No type specified"); } if (FieldQuery.query(typeSummary, field, FieldQuery.PRIVATE) == null) { throw new RefactoringException("Field named " + field + " does not exist in " + typeSummary.getName()); } TypeDeclSummary parentDecl = typeSummary.getParentClass(); parentType = GetTypeSummary.query(parentDecl); if (parentType == null) { throw new RefactoringException("Can't push up a field into source code that you don't have"); } checkDestinationFile(parentType, "Can't push up a field into source code that you don't have"); if (FieldQuery.query(parentType, field, FieldQuery.PRIVATE) != null) { throw new RefactoringException("Field named " + field + " already exists in parent class"); } if (FieldQuery.queryAncestors(typeSummary, field, FieldQuery.PRIVATE) != null) { throw new RefactoringException("Field named " + field + " already exists in an ancestor class"); } if (((FileSummary) parentType.getParent()).getFile() == null) { throw new RefactoringException("Can't push up a field into source code that you don't have"); } if (((FileSummary) typeSummary.getParent()).getFile() == null) { throw new RefactoringException("Can't push up a field from source code that you don't have"); } } /** * Actually update the files */ protected void transform() { FileSummary fileSummary = (FileSummary) getFileSummary(typeSummary); RemoveFieldTransform rft = new RemoveFieldTransform(field); ComplexTransform transform = getComplexTransform(); transform.add(rft); transform.apply(fileSummary.getFile(), fileSummary.getFile()); // Update the field declaration to have the proper permissions SimpleNode fieldDecl = rft.getFieldDeclaration(); if (fieldDecl == null) { return; } ASTFieldDeclaration decl = (ASTFieldDeclaration) fieldDecl.jjtGetChild(0); ModifierHolder holder = decl.getModifiers(); if (!holder.isPublic()) { holder.setPrivate(false); holder.setProtected(true); } AddFieldTransform aft = new AddFieldTransform(fieldDecl); transform.clear(); transform.add(aft); Object fieldType = getFieldType(fieldDecl, fileSummary); if (fieldType == null) { // Do nothing } else if ((fieldType instanceof TypeSummary) && !isInJavaLang((TypeSummary) fieldType)) { transform.add(new AddImportTransform((TypeSummary) fieldType)); } else if ((fieldType instanceof ASTName) && !isInJavaLang((ASTName) fieldType)) { transform.add(new AddImportTransform((ASTName) fieldType)); } FileSummary parentFileSummary = (FileSummary) parentType.getParent(); transform.apply(parentFileSummary.getFile(), parentFileSummary.getFile()); // Remove the field from all child classes (new RemoveFieldFromSubclassVisitor(parentType, typeSummary.getField(field), typeSummary, transform)).visit(null); } }